package com.rzgeo.rzmaplib.action;

import android.app.Activity;
import android.text.TextUtils;
import android.view.ActionMode;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;

import com.esri.arcgisruntime.concurrent.ListenableFuture;
import com.esri.arcgisruntime.data.Feature;
import com.esri.arcgisruntime.data.FeatureQueryResult;
import com.esri.arcgisruntime.data.FeatureTable;
import com.esri.arcgisruntime.data.Field;
import com.esri.arcgisruntime.data.QueryParameters;
import com.esri.arcgisruntime.geometry.Geometry;
import com.esri.arcgisruntime.geometry.Multipart;
import com.esri.arcgisruntime.geometry.Point;
import com.esri.arcgisruntime.geometry.Polygon;
import com.esri.arcgisruntime.geometry.Polyline;
import com.esri.arcgisruntime.layers.FeatureLayer;
import com.esri.arcgisruntime.mapping.view.Graphic;
import com.esri.arcgisruntime.mapping.view.GraphicsOverlay;
import com.esri.arcgisruntime.mapping.view.MapView;
import com.esri.arcgisruntime.mapping.view.SketchCreationMode;
import com.esri.arcgisruntime.mapping.view.SketchEditor;
import com.esri.arcgisruntime.mapping.view.SketchGeometryChangedEvent;
import com.esri.arcgisruntime.mapping.view.SketchGeometryChangedListener;
import com.rzgeo.rzmaplib.R;
import com.rzgeo.rzmaplib.RmlFeatureLayerQueryHelper;
import com.rzgeo.rzmaplib.util.RmlUtil;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.concurrent.ExecutionException;

/**
 * Created by zhanghang on 2018/1/27.
 */

public class RmlFreeDrawAction implements ActionMode.Callback, SketchGeometryChangedListener {
    private final MapView _mapView;
    private final SketchEditor _ske;
    private final GraphicsOverlay _tempGraphics;
    private final Activity _activity;
    private final FeatureLayer _targetLayer;
    private final String Var_DelSelect;
    private final String Var_LABEL_SET;
    private SketchEditor _oldSKE;
    private Geometry _curentGeo;
    private ActionMode _mode;


    public RmlFreeDrawAction(Activity activity, MapView mapView, FeatureLayer targetLayer) {
        _activity=activity;
        _mapView = mapView;
        _targetLayer=targetLayer;
        _ske = new SketchEditor();
        _tempGraphics=new GraphicsOverlay();

        _targetLayer.setSelectionWidth(2);
        Var_DelSelect=_activity.getString(R.string.rml_delselet);
        Var_LABEL_SET=_activity.getString(R.string.rml_lab_set);
    }

    @Override
    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
        _mode=mode;
        MenuInflater inflater = _activity.getMenuInflater();
        inflater.inflate(R.menu.rml_free_draw, menu);
        return true;
    }

    @Override
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        _oldSKE = _mapView.getSketchEditor();
        _mapView.setSketchEditor(_ske);
        _mapView.getGraphicsOverlays().add(_tempGraphics);
        _ske.addGeometryChangedListener(this);
        _ske.start(SketchCreationMode.FREEHAND_LINE);
        mode.setTitle("请在地图上滑动绘制曲线");
        return false;
    }

    @Override
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
        if (item.getItemId() == R.id.act_undo) {
            _curentGeo = null;
            if (_ske.getGeometry() != null)
                _ske.clearGeometry();
            else if (_tempGraphics.getGraphics().size() > 0)
                _tempGraphics.getGraphics().remove(_tempGraphics.getGraphics().size() - 1);
        }
        else if (item.getItemId() == R.id.act_label) {
            if(Var_LABEL_SET.equalsIgnoreCase(item.getTitle().toString())){
                RmlUtil.Tip.Toast("点击地图画出多边形，选择好后点击再次点击标注菜单设置备注");
                startSeletDraw();
                item.setTitle(R.string.rml_lab_set_2set);

            }else{
                item.setTitle(R.string.rml_lab_set);
                labelSelectFeature();
            }
        }
        else if (item.getItemId() == R.id.act_clear) {
            _tempGraphics.getGraphics().clear();
            _curentGeo=null;
            _ske.clearGeometry();
        }else if(item.getItemId() == R.id.act_sel_del){

            if(Var_DelSelect.equalsIgnoreCase(item.getTitle().toString())){
                RmlUtil.Tip.Toast("点击地图画出多边形，选择好后点击再次点击标注菜单，所有和多边形相交的涂鸦都会被删除");
                startSeletDraw();
                item.setTitle(R.string.rml_delselet_2del);

            }else{
                item.setTitle(R.string.rml_delselet);
                deleteSelectFeature();
            }
        }
        else if (item.getItemId() == R.id.act_cancel) {
            _mode.finish();
        }
        else if (item.getItemId() == R.id.act_ok) {
            if(_curentGeo==null&&_tempGraphics.getGraphics().size()==0)
            {
                RmlUtil.Tip.Toast("没有数据需要保存");
                _mode.finish();
                return true;
            }
            if(_targetLayer==null)
            {
                RmlUtil.Tip.Toast("没有图层");
                _mode.finish();
                return true;
            }
            if(!_targetLayer.getFeatureTable().isEditable())
            {
                RmlUtil.Tip.Toast("图层不可编辑");
                _mode.finish();
                return true;
            }

            ArrayList<Geometry>geos=new ArrayList<>(
                    1+_tempGraphics.getGraphics().size());
            geos.add(_curentGeo);
            for(Graphic g:_tempGraphics.getGraphics()){
                geos.add(g.getGeometry());
            }

            final FeatureTable ft = _targetLayer.getFeatureTable();
            ArrayList<Feature>features=new ArrayList<>(geos.size());

            for(Geometry g:geos){
                Feature f = ft.createFeature();
                f.setGeometry(g);
                features.add(f);
            }
            ft.addFeaturesAsync(features);
            ft.addDoneLoadingListener(new Runnable() {
                @Override
                public void run() {
                    RmlUtil.Tip.Toast("添加完成");
                    ft.removeDoneLoadingListener(this);
                }
            });
            _mode.finish();
        }
        else {
            return false;
        }
        return true;
    }

    private void startSeletDraw(){
        _tempGraphics.getGraphics().clear();
        _curentGeo=null;
        _ske.clearGeometry();
        _ske.start(SketchCreationMode.POLYGON);
    }

    private void labelSelectFeature() {
        RmlUtil.Tip.Toast("设置备注");
        _tempGraphics.getGraphics().clear();
        _curentGeo=null;
        _ske.clearGeometry();
        _ske.start(SketchCreationMode.FREEHAND_LINE);

        RmlUtil.Dialog.InputString(_activity, "", new RmlUtil.Dialog.OnInputText() {
            @Override
            public void onResult(final String content) {
                if(TextUtils.isEmpty(content)){
                    _mode.finish();
                }else{
                    final ListenableFuture<FeatureQueryResult> selectFeature = _targetLayer.getSelectedFeaturesAsync();

                    selectFeature.addDoneListener(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                _targetLayer.clearSelection();
                                FeatureTable ft = _targetLayer.getFeatureTable();
                                Field labelField = null;
                                for (Field f:ft.getFields()
                                     ) {
                                    if(f.getName().equalsIgnoreCase("lable")&&
                                            f.getFieldType()== Field.Type.TEXT){
                                        labelField=f;
                                        break;
                                    }
                                }
                                if(labelField==null){
                                    RmlUtil.Tip.Toast("数据包不包含标注字段");
                                    _mode.finish();
                                }


                                Iterator<Feature> iterator = selectFeature.get().iterator();
                                ArrayList<Feature> features = new ArrayList<>();
                                int count = 0;
                                while (iterator.hasNext()) {
                                    count++;
                                    Feature feature = iterator.next();
                                    if (ft.canUpdate(feature)){
                                        try {
                                            feature.getAttributes().put(labelField.getName(),content);
                                            features.add(feature);
                                        }catch (Exception e){

                                        }
                                    }
                                }

                                if (count != features.size()) {
                                    RmlUtil.Tip.Toast(String.format("有%个涂鸦无法更新设置", count - features.size()));
                                }


                                final ListenableFuture<Void> dr = ft.updateFeaturesAsync(features);
                                dr.addDoneListener(new Runnable() {
                                    @Override
                                    public void run() {
                                        try {
                                            dr.get();
                                        } catch (Exception e) {
                                            RmlUtil.Tip.Toast("无法更新");
                                        }
                                        _mode.finish();
                                    }
                                });
                            } catch (Exception e) {
                                RmlUtil.Log.Err(e);
                            }
                        }
                    });
                }
            }

            @Override
            public void onCancel() {
                _mode.finish();
            }
        });
    }

    private void deleteSelectFeature() {
        RmlUtil.Tip.Toast("删除涂鸦");
        _tempGraphics.getGraphics().clear();
        _curentGeo=null;
        _ske.clearGeometry();
        _ske.start(SketchCreationMode.FREEHAND_LINE);

        final ListenableFuture<FeatureQueryResult> selectFeature = _targetLayer.getSelectedFeaturesAsync();

        selectFeature.addDoneListener(new Runnable() {
            @Override
            public void run() {
                try {
                    FeatureTable ft = _targetLayer.getFeatureTable();

                    Iterator<Feature> iterator = selectFeature.get().iterator();
                    ArrayList<Feature> features = new ArrayList<>();
                    int count = 0;
                    while (iterator.hasNext()) {
                        count++;
                        Feature feature = iterator.next();
                        if (ft.canDelete(feature))
                            features.add(feature);
                    }
                    if (count != features.size()) {
                        RmlUtil.Tip.Toast(String.format("有%个涂鸦无法删除", count - features.size()));
                    }
                    final ListenableFuture<Void> dr = ft.deleteFeaturesAsync(features);
                    dr.addDoneListener(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                dr.get();
                            } catch (Exception e) {
                                RmlUtil.Tip.Toast("无法删除");
                            }
                            _mode.finish();
                        }
                    });
                } catch (Exception e) {
                    RmlUtil.Log.Err(e);
                }
            }
        });
    }

    @Override
    public void onDestroyActionMode(ActionMode mode) {
        _mapView.setSketchEditor(_oldSKE);
        _mapView.getGraphicsOverlays().remove(_tempGraphics);
        _tempGraphics.getGraphics().clear();
    }

    @Override
    public void geometryChanged(SketchGeometryChangedEvent e) {

        if(_ske.getSketchCreationMode()==SketchCreationMode.POLYGON){
            if (!_ske.isSketchValid()){
                return;
            }

            Polygon po = (Polygon) _ske.getGeometry();
            if(po.getParts().size()==0){
                return;
            }

            if(po.getParts().get(0).getPointCount()<3){
                return;
            }


            QueryParameters qp=new QueryParameters();
            qp.setGeometry(po);
            qp.setReturnGeometry(false);

            _targetLayer.selectFeaturesAsync(qp, FeatureLayer.SelectionMode.NEW);
        }else{
            if (!_ske.isSketchValid())
                return;
            if (_curentGeo == null) {
                _curentGeo = _ske.getGeometry();
            } else {
                Geometry geo2 = _ske.getGeometry();
                if (_curentGeo.getGeometryType() != geo2.getGeometryType()) {
                    pushLast();
                } else {
                    if (_curentGeo instanceof Point) {
                        pushLast();
                    } else if (_curentGeo instanceof Multipart) {
                        Multipart last = (Multipart) _curentGeo;
                        Multipart now = (Multipart) geo2;

                        if (last.getParts().get(0).getPointCount() < now.getParts().get(0).getPointCount()) {
                            _curentGeo = now;
                        } else {
                            pushLast();
                        }
                    } else {
                        _curentGeo = null;
                    }
                }
            }
        }
    }

    void pushLast() {
        if (_curentGeo == null) {
            return;
        } else if (_curentGeo instanceof Point) {
            _tempGraphics.getGraphics().add(
                    new Graphic(_curentGeo, RmlUtil.Copy.copy(_ske.getSketchStyle().getVertexSymbol()))
            );
        } else if (_curentGeo instanceof Polyline) {
            _tempGraphics.getGraphics().add(
                    new Graphic(_curentGeo, RmlUtil.Copy.copy(_ske.getSketchStyle().getLineSymbol()))
            );

        } else if (_curentGeo instanceof Polygon) {

            _tempGraphics.getGraphics().add(
                    new Graphic(_curentGeo, RmlUtil.Copy.copy(_ske.getSketchStyle().getFillSymbol()))
            );
        } else {
            RmlUtil.Log.Err("不支持几何类型" + _curentGeo.getGeometryType().toString());
        }
        _curentGeo = null;
    }
}
